using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using SqlsugarService.Application.AI.LangChain.Dtos;
using SqlsugarService.Application.AI.KouZi_AI;
using SqlsugarService.Application.AI.KouZi_AI.Dtos;
using System.Diagnostics;
using System.Text.Json;

namespace SqlsugarService.Application.AI.LangChain
{
    /// <summary>
    /// LangChain服务实现
    ///
    /// 基于扣子AI实现的智能对话服务，提供以下功能：
    /// - 基础对话功能 - 与扣子AI进行交互
    /// - 对话历史记忆 - 保持上下文连贯性
    /// - 链式工具调用 - 支持复杂的多步骤任务
    /// - 自定义提示词模板 - 控制AI的行为和输出
    /// </summary>
    public class LangChainService : ILangChainService
    {
        #region 私有字段

        /// <summary>
        /// 配置服务
        /// </summary>
        private readonly IConfiguration _configuration;

        /// <summary>
        /// 日志记录器
        /// </summary>
        private readonly ILogger<LangChainService> _logger;

        /// <summary>
        /// 扣子AI服务
        /// </summary>
        private readonly IKouZiAIService _kouziAIService;

        /// <summary>
        /// 会话记忆管理器
        /// 用于存储不同用户的对话历史
        /// </summary>
        private readonly Dictionary<string, List<ChatMessage>> _memoryStore = new();

        /// <summary>
        /// 聊天消息类
        /// </summary>
        public class ChatMessage
        {
            public string Role { get; set; } = string.Empty;
            public string Content { get; set; } = string.Empty;
            public DateTime Timestamp { get; set; } = DateTime.Now;
        }

        #endregion

        #region 构造函数

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="configuration">配置服务</param>
        /// <param name="logger">日志记录器</param>
        /// <param name="kouziAIService">扣子AI服务</param>
        public LangChainService(
            IConfiguration configuration,
            ILogger<LangChainService> logger,
            IKouZiAIService kouziAIService)
        {
            _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _kouziAIService = kouziAIService ?? throw new ArgumentNullException(nameof(kouziAIService));

            _logger.LogInformation("LangChain服务已初始化，使用扣子AI作为底层AI服务");
        }

        #endregion

        #region 公共方法

        /// <summary>
        /// 发送消息到扣子AI并获取回复
        /// </summary>
        /// <param name="request">请求参数</param>
        /// <returns>AI回复内容</returns>
        public async Task<LangChainResponseDto> SendMessageAsync(LangChainRequestDto request)
        {
            var stopwatch = Stopwatch.StartNew();
            var response = new LangChainResponseDto();

            try
            {
                _logger.LogInformation("开始处理LangChain消息（使用扣子AI），内容长度: {Length}", request.Content?.Length ?? 0);

                // 验证请求
                if (string.IsNullOrWhiteSpace(request.Content))
                {
                    throw new ArgumentException("消息内容不能为空", nameof(request.Content));
                }

                // 获取配置
                var systemPrompt = request.SystemPrompt ?? _configuration["LangChain:SystemPrompt"] ?? "你是一个有用的AI助手。";

                // 生成会话ID
                var sessionId = request.SessionId ?? Guid.NewGuid().ToString();
                var memoryKey = $"{request.UserId}:{sessionId}";

                // 构建完整的消息内容
                string fullContent = request.Content;

                // 如果启用记忆，获取历史对话并构建上下文
                if (request.EnableMemory)
                {
                    var chatHistory = GetOrCreateChatHistory(memoryKey, true);

                    // 添加当前用户消息到历史
                    chatHistory.Add(new ChatMessage
                    {
                        Role = "user",
                        Content = request.Content,
                        Timestamp = DateTime.Now
                    });

                    // 构建包含历史的完整消息
                    fullContent = BuildContextualMessage(chatHistory, systemPrompt);
                }
                else
                {
                    // 不启用记忆时，只使用系统提示词和当前消息
                    fullContent = $"{systemPrompt}\n\n用户: {request.Content}";
                }

                // 调用扣子AI服务
                var kouziResponse = await _kouziAIService.QuickSendAsync(fullContent, request.UserId);

                if (kouziResponse.Success)
                {
                    // 如果启用记忆，保存AI回复到历史
                    if (request.EnableMemory)
                    {
                        var chatHistory = GetOrCreateChatHistory(memoryKey, true);
                        chatHistory.Add(new ChatMessage
                        {
                            Role = "assistant",
                            Content = kouziResponse.Content ?? string.Empty,
                            Timestamp = DateTime.Now
                        });
                    }

                    // 构建响应
                    response.Success = true;
                    response.Content = kouziResponse.Content;
                    response.SessionId = sessionId;
                    response.ModelName = "KouZi-AI";
                    response.ProcessingTimeMs = stopwatch.ElapsedMilliseconds;

                    _logger.LogInformation("LangChain消息处理成功（使用扣子AI），耗时: {ElapsedMs}ms", stopwatch.ElapsedMilliseconds);
                }
                else
                {
                    response.Success = false;
                    response.ErrorMessage = kouziResponse.ErrorMessage ?? "扣子AI调用失败";
                    response.ProcessingTimeMs = stopwatch.ElapsedMilliseconds;
                }

                return response;
            }
            catch (Exception ex)
            {
                stopwatch.Stop();
                _logger.LogError(ex, "LangChain消息处理失败: {Message}", ex.Message);

                response.Success = false;
                response.ErrorMessage = $"处理失败: {ex.Message}";
                response.ProcessingTimeMs = stopwatch.ElapsedMilliseconds;
                return response;
            }
        }

        /// <summary>
        /// 快速发送消息（使用默认配置）
        /// </summary>
        /// <param name="content">消息内容</param>
        /// <param name="userId">用户ID，可选</param>
        /// <returns>AI回复内容</returns>
        public async Task<LangChainResponseDto> QuickSendAsync(string content, string? userId = null)
        {
            var request = new LangChainRequestDto
            {
                Content = content,
                UserId = userId ?? "default_user",
                EnableMemory = true
            };

            return await SendMessageAsync(request);
        }

        /// <summary>
        /// 清除指定用户的会话历史
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <param name="sessionId">会话ID，如果为null则清除该用户的所有会话</param>
        /// <returns>操作是否成功</returns>
        public Task<bool> ClearMemoryAsync(string userId, string? sessionId = null)
        {
            try
            {
                if (string.IsNullOrEmpty(sessionId))
                {
                    // 清除用户的所有会话
                    var keysToRemove = _memoryStore.Keys
                        .Where(k => k.StartsWith($"{userId}:"))
                        .ToList();

                    foreach (var key in keysToRemove)
                    {
                        _memoryStore.Remove(key);
                    }

                    _logger.LogInformation("已清除用户 {UserId} 的所有会话历史，共 {Count} 个", userId, keysToRemove.Count);
                }
                else
                {
                    // 清除特定会话
                    var memoryKey = $"{userId}:{sessionId}";
                    var removed = _memoryStore.Remove(memoryKey);
                    _logger.LogInformation("已{Result}清除用户 {UserId} 的会话 {SessionId} 历史",
                        removed ? "" : "尝试但未找到要", userId, sessionId);
                }

                return Task.FromResult(true);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "清除会话历史失败: {Message}", ex.Message);
                return Task.FromResult(false);
            }
        }

        /// <summary>
        /// 健康检查
        /// </summary>
        /// <returns>服务是否正常</returns>
        public async Task<bool> HealthCheckAsync()
        {
            try
            {
                // 检查扣子AI服务是否可用
                var kouziHealthy = await _kouziAIService.HealthCheckAsync();
                if (!kouziHealthy)
                {
                    _logger.LogWarning("LangChain健康检查失败: 扣子AI服务不可用");
                    return false;
                }

                _logger.LogInformation("LangChain健康检查通过");
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "LangChain健康检查失败: {Message}", ex.Message);
                return false;
            }
        }

        #endregion

        #region 私有方法

        /// <summary>
        /// 获取或创建聊天历史
        /// </summary>
        /// <param name="memoryKey">记忆键</param>
        /// <param name="enableMemory">是否启用记忆</param>
        /// <returns>聊天历史对象</returns>
        private List<ChatMessage> GetOrCreateChatHistory(string memoryKey, bool enableMemory)
        {
            if (!enableMemory)
            {
                return new List<ChatMessage>();
            }

            if (!_memoryStore.TryGetValue(memoryKey, out var chatHistory))
            {
                chatHistory = new List<ChatMessage>();
                _memoryStore[memoryKey] = chatHistory;
                _logger.LogDebug("为 {MemoryKey} 创建新的聊天历史", memoryKey);
            }

            return chatHistory;
        }

        /// <summary>
        /// 构建包含上下文的消息
        /// </summary>
        /// <param name="chatHistory">聊天历史</param>
        /// <param name="systemPrompt">系统提示词</param>
        /// <returns>完整的上下文消息</returns>
        private string BuildContextualMessage(List<ChatMessage> chatHistory, string systemPrompt)
        {
            var contextBuilder = new System.Text.StringBuilder();

            // 添加系统提示词
            contextBuilder.AppendLine(systemPrompt);
            contextBuilder.AppendLine();

            // 添加历史对话（最近的10轮对话）
            var recentHistory = chatHistory.TakeLast(20).ToList(); // 最近10轮对话（用户+助手=20条消息）

            if (recentHistory.Count > 1) // 如果有历史对话
            {
                contextBuilder.AppendLine("以下是之前的对话历史：");
                foreach (var message in recentHistory.Take(recentHistory.Count - 1)) // 排除当前消息
                {
                    var roleText = message.Role == "user" ? "用户" : "助手";
                    contextBuilder.AppendLine($"{roleText}: {message.Content}");
                }
                contextBuilder.AppendLine();
            }

            // 添加当前用户消息
            var currentMessage = recentHistory.LastOrDefault();
            if (currentMessage != null)
            {
                contextBuilder.AppendLine($"当前用户问题: {currentMessage.Content}");
            }

            return contextBuilder.ToString();
        }

        /// <summary>
        /// 构建包含工具信息的消息
        /// </summary>
        /// <param name="request">工具请求</param>
        /// <param name="systemPrompt">系统提示词</param>
        /// <param name="memoryKey">记忆键</param>
        /// <returns>完整的工具消息</returns>
        private string BuildToolMessage(LangChainToolRequestDto request, string systemPrompt, string memoryKey)
        {
            var messageBuilder = new System.Text.StringBuilder();

            // 添加系统提示词
            messageBuilder.AppendLine(systemPrompt);
            messageBuilder.AppendLine();

            // 如果有工具定义，添加工具信息
            if (request.Tools != null && request.Tools.Any())
            {
                messageBuilder.AppendLine("可用工具：");
                foreach (var tool in request.Tools)
                {
                    messageBuilder.AppendLine($"- {tool.Function.Name}: {tool.Function.Description}");
                    if (tool.Function.Parameters?.Properties != null && tool.Function.Parameters.Properties.Any())
                    {
                        messageBuilder.AppendLine("  参数：");
                        foreach (var param in tool.Function.Parameters.Properties)
                        {
                            messageBuilder.AppendLine($"    - {param.Key}: {param.Value}");
                        }
                    }
                }
                messageBuilder.AppendLine();
            }

            // 如果启用记忆，添加历史对话
            if (request.EnableMemory)
            {
                var chatHistory = GetOrCreateChatHistory(memoryKey, true);
                if (chatHistory.Any())
                {
                    messageBuilder.AppendLine("对话历史：");
                    var recentHistory = chatHistory.TakeLast(10).ToList();
                    foreach (var message in recentHistory)
                    {
                        var roleText = message.Role == "user" ? "用户" : "助手";
                        messageBuilder.AppendLine($"{roleText}: {message.Content}");
                    }
                    messageBuilder.AppendLine();
                }
            }

            // 添加当前用户消息
            messageBuilder.AppendLine($"当前用户问题: {request.Content}");

            return messageBuilder.ToString();
        }

        /// <summary>
        /// 发送带工具定义的消息，支持AI调用工具
        /// </summary>
        /// <param name="request">带工具定义的请求参数</param>
        /// <returns>AI回复内容，可能包含工具调用</returns>
        public async Task<LangChainToolResponseDto> SendMessageWithToolsAsync(LangChainToolRequestDto request)
        {
            var stopwatch = Stopwatch.StartNew();
            var response = new LangChainToolResponseDto();

            try
            {
                _logger.LogInformation("开始处理带工具的LangChain消息（使用扣子AI），工具数量: {ToolCount}", request.Tools?.Count ?? 0);

                // 验证请求
                if (string.IsNullOrWhiteSpace(request.Content))
                {
                    throw new ArgumentException("消息内容不能为空", nameof(request.Content));
                }

                // 获取配置
                var systemPrompt = request.SystemPrompt ?? _configuration["LangChain:SystemPrompt"] ?? "你是一个MES系统的智能助手，可以帮助用户查询数据和执行操作。";

                // 生成会话ID
                var sessionId = request.SessionId ?? Guid.NewGuid().ToString();
                var memoryKey = $"{request.UserId}:{sessionId}";

                // 构建包含工具信息的完整消息
                string fullContent = BuildToolMessage(request, systemPrompt, memoryKey);

                // 调用扣子AI服务
                var kouziResponse = await _kouziAIService.QuickSendAsync(fullContent, request.UserId);

                if (kouziResponse.Success)
                {
                    // 如果启用记忆，保存对话历史
                    if (request.EnableMemory)
                    {
                        var chatHistory = GetOrCreateChatHistory(memoryKey, true);
                        chatHistory.Add(new ChatMessage
                        {
                            Role = "user",
                            Content = request.Content,
                            Timestamp = DateTime.Now
                        });
                        chatHistory.Add(new ChatMessage
                        {
                            Role = "assistant",
                            Content = kouziResponse.Content ?? string.Empty,
                            Timestamp = DateTime.Now
                        });
                    }

                    response.Success = true;
                    response.Content = kouziResponse.Content;
                    response.SessionId = sessionId;
                    response.ModelName = "KouZi-AI";
                    response.ProcessingTimeMs = stopwatch.ElapsedMilliseconds;
                    response.ToolCalls = new List<ToolCall>(); // 扣子AI内置工具调用，不需要额外处理
                    response.RequiresAction = false;

                    _logger.LogInformation("带工具的LangChain消息处理成功（使用扣子AI），耗时: {ElapsedMs}ms", stopwatch.ElapsedMilliseconds);
                }
                else
                {
                    response.Success = false;
                    response.ErrorMessage = kouziResponse.ErrorMessage ?? "扣子AI调用失败";
                    response.ProcessingTimeMs = stopwatch.ElapsedMilliseconds;
                }

                return response;
            }
            catch (Exception ex)
            {
                stopwatch.Stop();
                _logger.LogError(ex, "带工具的Semantic Kernel消息处理失败: {Message}", ex.Message);

                response.Success = false;
                response.ErrorMessage = $"处理失败: {ex.Message}";
                response.ProcessingTimeMs = stopwatch.ElapsedMilliseconds;
                return response;
            }
        }

        /// <summary>
        /// 提交工具执行结果并继续对话
        /// </summary>
        /// <param name="request">工具执行结果</param>
        /// <returns>AI的后续回复</returns>
        public async Task<LangChainToolResponseDto> SubmitToolResultsAsync(ToolResultsRequest request)
        {
            var stopwatch = Stopwatch.StartNew();
            var response = new LangChainToolResponseDto();

            try
            {
                _logger.LogInformation("提交工具执行结果（使用扣子AI），工具调用ID: {ToolCallId}", request.ToolCallId);

                // 验证请求
                if (string.IsNullOrWhiteSpace(request.ToolCallId))
                {
                    throw new ArgumentException("工具调用ID不能为空", nameof(request.ToolCallId));
                }

                if (string.IsNullOrWhiteSpace(request.Output))
                {
                    throw new ArgumentException("工具执行结果不能为空", nameof(request.Output));
                }

                // 获取配置
                var systemPrompt = _configuration["LangChain:SystemPrompt"] ?? "你是一个MES系统的智能助手。";

                // 获取聊天历史
                var memoryKey = $"{request.UserId}:{request.SessionId}";
                var chatHistory = GetOrCreateChatHistory(memoryKey, true);

                // 添加工具执行结果到历史
                chatHistory.Add(new ChatMessage
                {
                    Role = "system",
                    Content = $"工具 {request.ToolCallId} 的执行结果: {request.Output}",
                    Timestamp = DateTime.Now
                });

                // 构建包含工具结果的消息
                var contextMessage = BuildContextualMessage(chatHistory, systemPrompt);
                contextMessage += $"\n\n请根据上述工具执行结果，为用户提供最终的回答。";

                // 调用扣子AI服务
                var kouziResponse = await _kouziAIService.QuickSendAsync(contextMessage, request.UserId);

                if (kouziResponse.Success)
                {
                    // 保存AI回复到聊天历史
                    chatHistory.Add(new ChatMessage
                    {
                        Role = "assistant",
                        Content = kouziResponse.Content ?? string.Empty,
                        Timestamp = DateTime.Now
                    });

                    response.Success = true;
                    response.Content = kouziResponse.Content;
                    response.SessionId = request.SessionId;
                    response.ModelName = "KouZi-AI";
                    response.ProcessingTimeMs = stopwatch.ElapsedMilliseconds;
                    response.ToolCalls = new List<ToolCall>();
                    response.RequiresAction = false;

                    _logger.LogInformation("工具结果提交处理成功（使用扣子AI），耗时: {ElapsedMs}ms", stopwatch.ElapsedMilliseconds);
                }
                else
                {
                    response.Success = false;
                    response.ErrorMessage = kouziResponse.ErrorMessage ?? "扣子AI调用失败";
                    response.ProcessingTimeMs = stopwatch.ElapsedMilliseconds;
                }

                return response;
            }
            catch (Exception ex)
            {
                stopwatch.Stop();
                _logger.LogError(ex, "工具结果提交失败: {Message}", ex.Message);

                response.Success = false;
                response.ErrorMessage = $"处理失败: {ex.Message}";
                response.ProcessingTimeMs = stopwatch.ElapsedMilliseconds;
                return response;
            }
        }

        #endregion
    }
}
